package gitobject;

import sha1.SHA1;
import zlib.ZLibUtils;
import java.io.*;
import java.util.*;

public class Tree extends GitObject{
    protected ArrayList<GitObject> treeList;	//GitObjects in tree

    public ArrayList<GitObject> getTreeList(){
        return treeList;
    }

    public Tree(){}

    /**
     * Constructor
     * @param file
     * @throws Exception
     */
    public Tree(File file) throws Exception {
        this.treeList = new ArrayList<GitObject>();
        this.fmt = "tree";
        this.mode = "040000";
        this.value = "";
        genKey(file);
        // 压缩文件的内容，并写入tree对象内(取消自动序列化，后续在JitHash手动序列化)
//        compressWrite();
    }

    public Tree(LinkedList<String> indexList) throws Exception {
        this.fmt = "tree";
        this.mode = "040000";
        this.value="";
        for(int i = 0; i<indexList.size() ; i++){
            value += indexList.get(i)+"\n";
        }
        genKey(this.value);
        // 压缩文件的内容，并写入tree对象内(取消自动序列化，后续在JitHash手动序列化)
//        compressWrite();
    }

    /**
     * Deserialize a tree object with treeId and its path.
     * @param Id
     * @param Id
     * @throws IOException
     */
    public static Tree deserialize(String Id) throws IOException {
        Tree tree = new Tree();
        tree.fmt = "tree";
        tree.mode = "040000";
        try{
            File file = new File(path + File.separator + Id.substring(0,2) + File.separator + Id.substring(2));
            if(file.exists()){
                tree.key = Id;
                FileInputStream input = new FileInputStream(file);
                byte[] byt = ZLibUtils.decompress(input);
                tree.value = new String(byt);
                input.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return tree;
    }


    /**
     * Sort the files in a certain order. You should consider whether it's a file or a directory.
     * @param fs
     * @return List
     */
    // 主要根据文件类型,文件名排序
    public List sortFile(File[] fs){
        List fileList = Arrays.asList(fs);
        Collections.sort(fileList, new Comparator<File>() {
            @Override //表示重写方法
            public int compare(File o1, File o2) {
                if(o1.isFile()&& o2.isDirectory()){
                    return 1;
                }
                if(o1.isDirectory()&&o2.isFile()){
                    return -1;
                }
                return o1.getName().compareTo(o2.getName());
            }
        });
        return fileList;
    }

    /**
     * Generate the key of a tree object.
     * @param dir
     * @return String
     * @throws Exception
     */
    // tree的key值需要根据存储的记录(value)决定，因此要遍历内部的对象
    public String genKey(File dir) throws Exception{
        File[] fs = dir.listFiles();
        List sortFs = sortFile(fs);

        for(int i = 0; i<sortFs.size() ; i++){
            // 如果存储file对象，那么在tree.value中加上
            if(fs[i].isFile()){
                Blob blob = new Blob(fs[i]);
                value += blob+ " " + fs[i].getName() + "\n";
            }else if(fs[i].isDirectory()){
                // 如果是文件夹，那么递归继续遍历
                Tree tree = new Tree(fs[i]);
                // tree的有参构造自动调用genKey，直接接收返回的值即可
                value += tree + " " + fs[i].getName() + "\n";
            }
        }
        key = SHA1.getHash(fmt+" "+value.length()+"\0"+value);
        return key;
    }

    public String genKey(String value) throws Exception{
        key = SHA1.getHash(fmt+" "+value.length()+"\0"+value);
        return key;
    }

    @Override
    public String toString(){
        return mode+" " +fmt+" " + key;
    }

}
